import os
import threading
from datetime import datetime

import numpy as np
import pandas as pd
import xarray as xr
from apscheduler.schedulers.blocking import BlockingScheduler
from ecmwf.opendata import Client

parameters = ['tp']
os.makedirs("./data", exist_ok=True)
filename = './data/aifs_ens_cf_medium_tp_tcc.grib'

download_ecmwf_timestamp = None
download_ecmwf_df = None


def download_latest_ecmwf_open_data():
    global download_ecmwf_timestamp
    global download_ecmwf_df

    try:
        if (download_ecmwf_timestamp is None
                or (datetime.now() - download_ecmwf_timestamp).total_seconds() > 3600):
            download_ecmwf_timestamp = datetime.now()
        else:
            return None

        client = Client("ecmwf", beta=False, model="aifs-ens")

        now_utc = datetime.utcnow()

        available_time = now_utc - timedelta(hours=5)
        available_hour = available_time.hour

        # 根据可用时间确定最新的预报时次
        if available_hour >= 18:
            time = 18
        elif available_hour >= 12:
            time = 12
        elif available_hour >= 6:
            time = 6
        elif available_hour >= 0:
            time = 0

        print(f'下载中：https://data.ecmwf.int/forecasts/{available_time.strftime("%Y%m%d")}/{time:02d}z')

        client.retrieve(
            date=available_time.strftime("%Y-%m-%d"),
            time=time,
            step=12,
            stream="enfo",
            type="cf",
            levtype="sfc",
            param=parameters,
            target=filename
        )

        # 打开GRIB2文件
        ds = xr.open_dataset(filename, engine="cfgrib")

        # 转换整个数据集，包含所有变量
        df = ds.to_dataframe().reset_index()

        download_ecmwf_df = df

    except Exception as e:
        print(e)


from flask import Flask
from flask_cors import CORS
import logging
from datetime import timedelta

from flask import Blueprint, request
from flask import jsonify
from flask_apscheduler import APScheduler

bp = Blueprint('aifs', __name__, url_prefix='/aifs')


@bp.post('/get_forecast')
def get_forecast():
    try:
        global download_ecmwf_timestamp
        global download_ecmwf_df

        data = request.get_json()
        lat = data.get('lat')
        lon = data.get('lon')

        # 验证参数
        if not lat or not lon:
            return jsonify({'error': '缺少经纬度参数'}), 400

        lat = float(lat)
        lon = float(lon)

        df_local = download_ecmwf_df.copy()

        # 计算距离（简单的欧几里得距离）
        df_local['distance'] = np.sqrt(
            (df_local['latitude'] - lat) ** 2 +
            (df_local['longitude'] - lon) ** 2
        )

        # 找到最近的点
        closest_idx = df_local['distance'].idxmin()
        closest_point = df_local.loc[closest_idx]

        valid_time_utc = closest_point.get('valid_time')

        # 转换为pandas时间戳并加8小时
        beijing_time = pd.Timestamp(valid_time_utc) + pd.Timedelta(hours=8)
        valid_time_str = beijing_time.strftime('%Y-%m-%d %H:%M:%S CST')

        # 提取预报数据
        forecast_data = {
            'status': 200,
            'requested_lat': lat,
            'requested_lon': lon,
            'actual_lat': float(closest_point['latitude']),
            'actual_lon': float(closest_point['longitude']),
            'distance_km': float(closest_point['distance'] * 111),  # 转换为公里
            'total_precipitation': float(closest_point.get('tp', 0)),  # mm
            'total_cloud_cover': float(closest_point.get('tcc', 0)) if closest_point.get('tcc') is not None else None,
            'valid_time': valid_time_str
        }

        return jsonify(forecast_data)
    except Exception as e:
        print(e)


scheduler = APScheduler()


@scheduler.task('interval', id='task_1', seconds=3600, misfire_grace_time=900)
def task1():
    print('task 1 executed --------', datetime.now())
    download_latest_ecmwf_open_data()


class BaseConfig:
    SECRET_KEY = "fsfsd482afewfwhudsdkckznknajdhuwrhafnf"

    # 数据库的配置信息
    # SQLALCHEMY_DATABASE_URI = 'sqlite:///../data.db'

    # 默认日志等级
    LOG_LEVEL = logging.WARN

    SEND_FILE_MAX_AGE_DEFAULT = timedelta(hours=48)

    # SOCK_SERVER_OPTIONS = {'ping_interval': 25}

    SCHEDULER_API_ENABLED = True


def init_bps(app):
    # 在admin_bp下注册子蓝图
    app.register_blueprint(bp)


def create_app():
    app = Flask(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

    # 启用CORS，允许所有源访问
    CORS(app)

    # 引入配置
    app.config.from_object(BaseConfig)

    # 注册蓝图
    init_bps(app)

    return app


if __name__ == "__main__":
    download_latest_ecmwf_open_data()

    app = create_app()

    scheduler.init_app(app)
    scheduler.start()

    app.run(
        host='0.0.0.0',
        port=12001,
        debug=True,
        use_reloader=False
    )
